﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MayhemCore;
using System.Runtime.Serialization;
using MayhemWpf.ModuleTypes;
using SensorHOL;
using Microsoft.WindowsAPICodePack.Sensors;
using System.Windows.Media.Media3D;
using MayhemWpf.UserControls;
using SensorMayhem.Wpf;

namespace SensorMayhem.Events
{

    public static class OrientationTypes
    {
        public static OrientationType LayingUpsideUp = new OrientationType() { Name = "Laying upside up", Orientations = new Vector3D[] { new Vector3D(0, 0, -1) } };
        public static OrientationType LayingUpsideDown = new OrientationType() { Name = "Laying upside down", Orientations = new Vector3D[] { new Vector3D(0, 0, 1) } };
        public static OrientationType Landscape = new OrientationType() { Name = "Standing in landscape", Orientations = new Vector3D[] { new Vector3D(0, -1, 0), new Vector3D(0, 1, 0) } };
        public static OrientationType Portrait = new OrientationType() { Name = "Standing in portrait", Orientations = new Vector3D[] { new Vector3D(-1, 0, 0), new Vector3D(1, 0, 0) } };
    }

    [Serializable]
    public class OrientationType
    {
        public string Name { get; set; }
        public Vector3D[] Orientations { get; set; }

        public override string ToString()
        {
            return Name;
        }
    }

    [DataContract]
    [MayhemModule("Sensor: Orientation", "Triggers when the computer is in a specified orientation")]
    public class Orientation : EventBase, IWpfConfigurable
    {

        SensorHelper<Accelerometer3D, Acceleration3D> accelerometerSensor;

        private bool triggered = false;

        [DataMember]
        private OrientationType orientation;

        protected override void OnLoadDefaults()
        {
            orientation = OrientationTypes.LayingUpsideDown;
        }

        protected override void OnEnabling(EnablingEventArgs e)
        {
            try
            {
                accelerometerSensor = new SensorHelper<Accelerometer3D, Acceleration3D>();
                accelerometerSensor.Initialize();
                accelerometerSensor.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(accelerometerSensor_PropertyChanged);
            }
            catch (Exception)
            {

            }

        }

        void accelerometerSensor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            var a3d = accelerometerSensor.Value as Acceleration3D;
            if (a3d != null)
            {
                float x = a3d[AccelerationAxis.XAxis];
                float y = a3d[AccelerationAxis.YAxis];
                float z = a3d[AccelerationAxis.ZAxis];

                bool trigger = IsInSelectedOrientation(x, y, z);
                if (trigger && !triggered)
                {
                    Trigger();
                    triggered = true;
                }
                else if (IsAwayFromOrientation(x, y, z))
                {
                    ResetTrigger();
                }
            }
        }

        bool IsInSelectedOrientation(float x, float y, float z)
        {
            foreach (var item in orientation.Orientations)
            {
                if (Math.Abs(item.X - x) < 0.1 && Math.Abs(item.Y - y) < 0.1 && Math.Abs(item.Z - z) < 0.1)
                {
                    return true;
                }
            }
            return false;
        }

        bool IsAwayFromOrientation(float x, float y, float z)
        {
            foreach (var item in orientation.Orientations)
            {
                if (Math.Abs(item.X - x) > 0.3 || Math.Abs(item.Y - y) > 0.3 || Math.Abs(item.Z - z) > 0.3)
                {
                    return true;
                }
            }
            return false;
        }
        

        void ResetTrigger()
        {
            triggered = false;
        }

        protected override void OnDisabled(DisabledEventArgs e)
        {
            try
            {
                accelerometerSensor.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(accelerometerSensor_PropertyChanged);
            }
            catch (Exception)
            {

            }
            ResetTrigger();
        }

        public WpfConfiguration ConfigurationControl
        {
            get
            {
                return new OrientationConfig(orientation);
            }
        }

        public void OnSaved(WpfConfiguration configurationControl)
        {
            OrientationConfig config = configurationControl as OrientationConfig;
            orientation = config.Orientation;
        }

        public string GetConfigString()
        {
            return orientation.Name;
        }

    }
}
